/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package x2rel.qMap.core;

import java.io.File;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import x2rel.qMap.logger.Logging;

/**
 *
 * @author Leonardo Nicorena <lnicorena at inf.ufsm.br>
 */
public class AlgebraRelHandler extends XmlHandler {

    private ArrayList<Equivalencias> eqs;
    private String alg;
    private ArrayList<Variables> vars;

    public AlgebraRelHandler(ArrayList<Equivalencias> equivs, ArrayList<Variables> vars) {

        this.alg = "";

        this.eqs = equivs;
        
        this.vars = vars;

    }

    protected String generateAlgRel() {
        if (this.eqs.size() > 0) {
            try {
                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

                //root elements
                Document doc = docBuilder.newDocument();

                Element rootElement = doc.createElement("relational_algebra");
                doc.appendChild(rootElement);


                Element expression = doc.createElement("expression");
                rootElement.appendChild(expression);

                ArrayList<String> tables = new ArrayList<String>();
                for (int i = 0; i < this.eqs.size(); i++) {
                    Equivalencias e = this.eqs.get(i);
                    String t = e.getTable();
                    if (!tables.contains(t)) {
                        tables.add(t);
                    }
                }

                Element rel = doc.createElement("relations");
                expression.appendChild(rel);
                for (String t : tables) {
                    if (!t.isEmpty()) {
                        Element tab = doc.createElement("table");
                        tab.appendChild(doc.createTextNode(t));
                        rel.appendChild(tab);
                    }
                }


                Element sel = doc.createElement("selection");
                Boolean wflag = false;

                Boolean rflag = false;
                Element ret = doc.createElement("projection");
                expression.appendChild(ret);
                Element columnlist = doc.createElement("columnlist");
                ret.appendChild(columnlist);


                for (int i = 0; i < this.eqs.size(); i++) {
                    Equivalencias e = this.eqs.get(i);
                    /*
                    if (e.getTipo().equalsIgnoreCase("For")) {
                    Logging.getInstance().log("Equivalencia!\n" + e.getColumn());
                    Logging.getInstance().log("Equivalencia!\n" + e.getDomain());
                    Logging.getInstance().log("Equivalencia!\n" + e.getTable());
                    }
                     */
                    if (e.getTipo().equalsIgnoreCase("Return")) {
                        // do something
                        rflag = true;

                        Element column = doc.createElement("column");
                        Attr attr = doc.createAttribute("table");
                        if (e.getType().equalsIgnoreCase("Table")) {
                            attr.setValue(e.getName());
                            column.setAttributeNode(attr);
                            column.appendChild(doc.createTextNode("*"));
                        } else {
                            attr.setValue(e.getTable());
                            column.setAttributeNode(attr);
                            column.appendChild(doc.createTextNode(e.getColumn()));
                        }
                        columnlist.appendChild(column);

                    }

                    if (e.getTipo().equalsIgnoreCase("Where")) {
                            
                        if (!wflag) {
                            expression.appendChild(sel);
                            wflag = true;
                        }else{
                            Element wop = doc.createElement("logical_op");
                            wop.appendChild(doc.createTextNode(getVarByCod(vars, e.getCod()).getWhere_op()));
                            sel.appendChild(wop);
                        }
                            Element condlist = doc.createElement("condlist");
                            sel.appendChild(condlist);

                            Element column = doc.createElement("column");
                            Attr attr = doc.createAttribute("table");
                            attr.setValue(e.getTable());
                            column.setAttributeNode(attr);
                            column.appendChild(doc.createTextNode(e.getColumn()));
                            condlist.appendChild(column);
                            
                            Element comp_op = doc.createElement("comp_op");
                            comp_op.appendChild(doc.createTextNode(getVarByCod(vars, e.getCod()).getWhere()));
                            condlist.appendChild(comp_op);
                            
                            Element data = doc.createElement("data");
                            data.appendChild(doc.createTextNode(getVarByCod(vars, e.getCod()).getValue()));
                            condlist.appendChild(data);
                            
                        
                    }
                }

                if (!rflag) {
                    /*
                    Element ret = doc.createElement("projection");
                    expression.appendChild(ret);
                    
                    Element columnlist = doc.createElement("columnlist");
                    ret.appendChild(columnlist);
                     */
                    for (int i = 0; i < this.eqs.size(); i++) {
                        Equivalencias e = this.eqs.get(i);
                        if (e.getTipo().equalsIgnoreCase("For")) {
                            Element column = doc.createElement("column");
                            Attr attr = doc.createAttribute("table");
                            attr.setValue(e.getTable());
                            column.setAttributeNode(attr);
                            column.appendChild(doc.createTextNode(e.getColumn()));
                            columnlist.appendChild(column);

                        }
                    }
                }


                //write the content into xml file
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                DOMSource source = new DOMSource(doc);

                SimpleDateFormat date_format = new SimpleDateFormat("yyyyMMddHHmmss");
                String date = date_format.format(new Date());
                StreamResult result = new StreamResult(new File("outputs\\output_" + date + ".xml"));
                transformer.transform(source, result);

                StreamResult result2 = new StreamResult(new StringWriter());
                transformer.transform(source, result2);
                String xmlString = result2.getWriter().toString();

                Logging.getInstance().log("Algebra relacional salva com sucesso.");
                Logging.getInstance().log(xmlString);

                return xmlString;


            } catch (ParserConfigurationException pce) {
                Logging.getInstance().log(pce.getMessage(), 3);
            } catch (TransformerException tfe) {
                Logging.getInstance().log(tfe.getMessage(), 3);
            }

        }

        return "";

    }
}
